/// <reference name="MicrosoftAjax.debug.js" />
/// <reference path="../../Resources/js/jquery/jquery.debug.js" />
/// <reference path="../Items/MItem.js" />
/// <reference path="../Root.js" />

Type.registerNamespace("BM");

BM.ValidationErrorElement = function(itemId, errorText) {
    this.itemId = itemId;
    this.span = document.createElement('span');
    this.setErrorText(errorText);
}

BM.ValidationErrorElement.createFromNode = function(itemId, node) {
    var validationErrorElement = new BM.ValidationErrorElement(itemId, null);
    validationErrorElement.element = node;
    validationErrorElement.span = $(node).children('span')[0];
    return validationErrorElement;
}

BM.ValidationErrorElement.prototype = {
    getElement: function() {
        if (this.element == null) {
            this.element = this._createElement();
        }
        $(this.span).text(this.getErrorText());
        return this.element;
    },

    _createElement: function() {
        var element = document.createElement('div');
        var link = document.createElement('a');
        element.appendChild(link);
        link.setAttribute('href', '#');
        link.onclick = Function.createDelegate(this, this.go);
        $(link).text(this.getItem().getName());
        var text = document.createTextNode(': ');
        element.appendChild(text);
        element.appendChild(this.span);
        return element;
    },

    getItem: function() {
        return MItem.getById(this.itemId);
    },

    setErrorText: function(errorText) {
        $(this.span).text(errorText);
    },

    getErrorText: function() {
        return $(this.span).text();
    },

    go: function() {
        this.getItem().focus();
        return false;
    }
}

BM.RootValidator = function(node) {
    ///	<summary locid="T:J#BM.RootValidator">
    ///	This class is responsible for validating the MForm tree and for keeping information about which controls 
    /// are not valid    
    ///	</summary>
    ///	<param name="node" type="HTMLElement">
    ///	the html control element
    ///	</param>      
    ///	<returns type="BM.RootValidator" />
    BM.RootValidator.initializeBase(this, [node]);
    node.evaluationfunction = BM.RootValidator.run;
    this.itemsWithError = this._readServerSideItemsWithError();
}

BM.RootValidator.prototype = {
    set_rootId: function(rootId) {
        this.rootId = rootId;
    },

    get_rootId: function() {
        return this.rootId;
    },

    initialize: function() {
        BM.RootValidator.callBaseMethod(this, 'initialize');        
        if (this.getRoot() != null) {
            this.registerItemCreatedHandler();
        } else {
            Sys.Application.add_load(Function.createDelegate(this, this.registerItemCreatedHandler));
        }                
    },

    registerItemCreatedHandler: function() {
        if (this.getRoot()) {
            this.getRoot().add_itemCreated(Function.createDelegate(this, this.onItemCreated));
        }
    },

    onItemCreated: function(sender, args) {
        args.item.addValidationError(Function.createDelegate(this, this.notifyAboutError));
        args.item.addValidationSuccess(Function.createDelegate(this, this.notifyAboutSuccess));
        if (ChoiceItem.isInstanceOfType(args.item)) {
            args.item.addValidationSuccess(Function.createDelegate(this, this.updateErrorsVisibility));
            args.item.addValidationError(Function.createDelegate(this, this.updateErrorsVisibility));
        }
    },

    getRoot: function() {
        return $find(this.get_rootId());
    },

    itemRemoved: function(sender, eventArgs) {
        this.notifyAboutSuccess(sender);
    },

    notifyAboutError: function(source, args) {
        var validationError = args[0];
        if (!this.itemsWithError[validationError.item.getId()]) {
            validationError.item.addUnloading(Function.createDelegate(this, this.itemRemoved));
            var itemId = validationError.getItem().getId()
            var errorElementHandler = new BM.ValidationErrorElement(itemId, validationError.getErrorText());
            this.itemsWithError[itemId] = errorElementHandler;
            this.get_element().appendChild(errorElementHandler.getElement());
            this.get_element().style.visibility = 'visible';
        }
        else {
            this.itemsWithError[validationError.getItem().getId()].setErrorText(validationError.getErrorText());
        }
    },

    notifyAboutSuccess: function(source, args) {
        var item = source;
        item.removeUnloading(Function.createDelegate(this, this.itemRemoved));
        var id = item.getId();
        if (this.itemsWithError[id]) {
            this.get_element().removeChild(this.itemsWithError[id].getElement());
            delete this.itemsWithError[id];
        }
    },

    updateErrorsVisibility: function() {
        for (var key in this.itemsWithError) {
            var errorHandler = this.itemsWithError[key];
            if (errorHandler.getItem().isInUse()) {
                errorHandler.getElement().style.display = 'block';
            } else {
                errorHandler.getElement().style.display = 'none';
            }
        }
    },

    focusFirst: function() {
        for (var key in this.itemsWithError) {
            var validationError = this.itemsWithError[key];
            if (validationError.getItem().isInUse()) {
                validationError.getItem().focus();
                return;
            }
        }
    },

    _readServerSideItemsWithError: function() {
        var items = new Object();
        var divs = $(this.get_element()).children('div');
        for (var i = 0; i < divs.length; i++) {
            var currentDiv = divs[i];
            var itemId = this._getIdFromDiv(currentDiv);
            items[itemId] = BM.ValidationErrorElement.createFromNode(itemId, currentDiv);
        }
        return items;
    },

    _getIdFromDiv: function(div) {
        var onclick = $(div).children('a')[0].onclick.toString();
        var bracketStart = onclick.lastIndexOf('(');
        var bracketEnd = onclick.lastIndexOf(')');
        return onclick.substring(bracketStart + 2, bracketEnd - 1);
    }
}

BM.RootValidator.registerClass("BM.RootValidator", Sys.UI.Control);

BM.RootValidator.run = function(source, arguments) {
    var validator = $find(source.id);
    var root = validator.getRoot();
    if (root != null && root.getRootItem() != null) {
        var validationResult = root.getRootItem().validate();
        validator.focusFirst();
        return validationResult;
    }

    return true;
}

